package xcollections;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.lang.reflect.Method;

import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;

import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeMultipart;
import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils.IO;

public class Xtask implements java.io.Serializable{
	
	//returns the name of the type of the collection 
	void getCollectionName(Collection unknownCollection) {
		isExisting(unknownCollection);
		System.out.println("The class of " + unknownCollection +
                " is " + unknownCollection.getClass().getName());
	}

	private void isExisting(Collection unknownCollection) {
		if (unknownCollection == null ) {
			throw new IllegalArgumentException("Collection does not exist!");
		}
	}

	//finds the main type of Objects in the collection
	
	Object findMainType(Collection unknownCollection) {
		isExisting(unknownCollection);
		String typeOfFirstObj = "";
		String typeOfSecondObj = "";
		String mainType = "";
		Object main = null;
		Iterator iter = unknownCollection.iterator();
		while (iter.hasNext()) {
			Object element = iter.next();
			typeOfFirstObj = element.getClass().getName();
			
			if (typeOfFirstObj.equals(typeOfSecondObj)) {
				mainType = typeOfFirstObj;
				main = element;
				break;
			}
			mainType = typeOfFirstObj;
			typeOfSecondObj = mainType;
		} return main;
	}
	
	//creates another collection (copy of 1st), and removes the black sheep from it
	Collection removeBlackSheep(Collection unknownCollection, Object mainType) {
		if (unknownCollection == null || mainType == null) {
			throw new IllegalArgumentException();
		}
		Collection secondCollection = null;
		try {
			String someClass = unknownCollection.getClass().getName();
			Class myclass = Class.forName(someClass);
	        secondCollection = (Collection) myclass.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		for (Object o : unknownCollection) {
			if (o.getClass().equals(mainType.getClass()))
				secondCollection.add(o);
			else
				continue;
		}
		return secondCollection;		
	}
	
	//prints the name of the methods, which the given class in the collection has
	void printMethodsFromClass(Collection unknownCollection) {
		isExisting(unknownCollection);		
		if (unknownCollection != null){
			Method [] methods = null;
			for (Object o : unknownCollection) {
				methods = o.getClass().getDeclaredMethods();
				break;
			}for (Method method : methods) {
				System.out.println(method.getName());
			}
		} 	
	}
	
	//print all objects in collection
	void printObjectsInCollection(Collection unknownCollection) {
		if (unknownCollection != null)
			for (Object o:unknownCollection) {
				System.out.println(o.getClass().getName());
			}
	}
	
	//serialize the objects in collection and returns the name of the file .ser
	String serializeCollection(Collection unknownCollection) throws ClassNotFoundException {
		isExisting(unknownCollection);
		ObjectOutputStream out = null;
		String fileName = "";
		try{
			 // Serialize data object to a file
			fileName = "myObj.ser";
			 out = new ObjectOutputStream(new FileOutputStream(fileName));
			 for (Object o: unknownCollection)
				 out.writeObject(o);
			 out.close();
			 
			return fileName;	
		}
		catch (IOException e) {
			 e.printStackTrace();
			 return "";
		}finally {
			try {
				out.close();
				return fileName;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	//should be sending text AND file
	void sendToMail(String filename) throws MessagingException {
		 Transport transportSSL = null;
		try{
			 final String userName = "michailangelov@abv.bg";
			 final String passWord = "setdeusexjcd";
			 Properties propsSSL = new Properties();
			 propsSSL.put("mail.transport.protocol", "smtps");
			 propsSSL.put("mail.smtps.host", "smtp.abv.bg");
			 propsSSL.put("mail.smtps.auth", "true");
//			 propsTLS.put("mail.smtp.starttls.enable", "true"); // GMail requires STARTTLS
			 Session sessionSSL = Session.getInstance(propsSSL,
			            new javax.mail.Authenticator() {
			                protected PasswordAuthentication getPasswordAuthentication() {
			                    return new PasswordAuthentication(userName, passWord);
			                }
			            });
//			 sessionTLS.setDebug(true);
			 Message messageSSL = new MimeMessage(sessionSSL);
			 messageSSL.setFrom(new InternetAddress(userName, "JAVA_MAIL"));
			 messageSSL.setRecipients(Message.RecipientType.TO, InternetAddress.parse(userName)); 
			 messageSSL.setSubject("Test mail using SSL");
			 messageSSL.setText("Surprise if this works");
			 
			 transportSSL = sessionSSL.getTransport();
			 System.out.println("thiinkin");
			 transportSSL.connect("smtp.abv.bg", 465, userName, passWord); 
			 
			 transportSSL.sendMessage(messageSSL, messageSSL.getAllRecipients());
			 // Create a multipart message
			 BodyPart messageBodyPart = new MimeBodyPart();
	         Multipart multipart = new javax.mail.internet.MimeMultipart();
	         multipart.addBodyPart(messageBodyPart);
	         
	         messageBodyPart = new MimeBodyPart();
	         messageBodyPart.setDataHandler(new DataHandler(new FileDataSource(filename)));
	         messageBodyPart.setFileName(filename);
	         multipart.addBodyPart(messageBodyPart);
	         
	         messageSSL.setContent(multipart);
	         Transport.send(messageSSL);
	         System.out.println("Sent message successfully....");
	         transportSSL.close();
		}catch(Exception e) {
			e.printStackTrace();
			System.out.println("Problem!");
		} finally {
			transportSSL.close();
		}
	}

	public static void main(String[] args) throws Exception {
		
		Xtask task = new Xtask();				
		ArrayList glist = new ArrayList();
		task.getCollectionName(glist);
		
		Opit o1 = new Opit();
		Opit o2 = new Opit();
		Opit o3 = new Opit();
		Opit2 o4 = new Opit2();
		glist.add(o1);
		glist.add(o2);
		glist.add(o3);
		glist.add(o4);
		
		Object main = task.findMainType(glist);
		Collection secondCollection = task.removeBlackSheep(glist, main);
		task.printObjectsInCollection(secondCollection);
		System.out.println();
		task.printMethodsFromClass(glist);		
		String file = task.serializeCollection(glist);
		task.sendToMail(file);
		
	}
}
